In computing, a namespace is a set of signs ( names) that are used to identify and refer to objects of various kinds. A namespace ensures that all of a given set of objects have unique names so that they can be easily Identifier.
Namespaces are commonly structured as hierarchies to allow reuse of names in different contexts. As an analogy, consider a system of Anthroponymy where each person has a given name, as well as a family name shared with their relatives. If the first names of family members are unique only within each family, then each person can be uniquely identified by the combination of first name and family name; there is only one Jane Doe, though there may be many Janes. Within the namespace of the Doe family, just "Jane" suffices to unambiguously designate this person, while within the "global" namespace of all people, the full name must be used.
Prominent examples for namespaces include , which assign names to files. Some programming languages organize their variables and in namespaces. and distributed systems assign names to resources, such as , printers, , and remote files. can partition kernel resources by isolated namespaces to support virtualization containers.
Similarly, hierarchical file systems organize files in directories. Each directory is a separate namespace, so that the directories "letters" and "invoices" may both contain a file "to_jane".
In computer programming, namespaces are typically employed for the purpose of grouping symbols and identifiers around a particular functionality and to avoid between multiple identifiers that share the same name.
In Computer network, the Domain Name System organizes websites (and other resources) into hierarchical namespaces.
This XML carries HTML table information:
Apples
Oranges
If these XML fragments were added together, there would be a name conflict. Both contain a element, but the elements have different content and meaning.
An XML parser will not know how to handle these differences.
The following XML distinguishes between information about the HTML table and furniture by prefixing "h" and "f" at the beginning of the elements.
In augmented Backus–Naur form:
+ Examples of names in a namespace | |
(domain name) | |
Mona Lisa | |
(file name) | |
(file name) | |
(class) | |
(class) | |
(locality) | |
(element) | |
(variable) | |
(class) | |
(class) | |
(handle local name) | |
(publication) | |
(NIC specific) | |
(device ID) | |
Stephen J. Gowdy. "List of USB ID's". 2013. | (product ID) |
A hierarchy is recursive if the syntax for the namespace names is the same for each subdelegation. An example of a recursive hierarchy is the Domain name.
An example of a non-recursive hierarchy are Uniform Resource Name representing an Internet Assigned Numbers Authority (IANA) number.
+ Hierarchical namespace breakdown for , an identifier for the book The Logic of Scientific Discovery by Karl Popper, 10th edition. |
Formal URN namespace |
International Standard Book Numbers as Uniform Resource Names |
Bookland |
German-speaking countries |
Mohr Siebeck |
+Examples of naming systems with local and global scope, and with and without namespaces ! !! Without a namespace !! With a namespace |
Filesystem Hierarchy Standard |
Domain Name System |
As a rule, names in a namespace cannot have more than one meaning; that is, different meanings cannot share the same name in the same namespace. A namespace is also called a context, because the same name in different namespaces can have different meanings, each one appropriate for its namespace.
Following are other characteristics of namespaces:
As well as its abstract language technical usage as described above, some languages have a specific keyword used for explicit namespace control, amongst other uses. Below is an example of a namespace in C++:
// This is how one brings a name into the current scope. In this case, it's
// bringing them into global scope.
using std::println;
namespace box1 {
namespace box2 {
int main() {
constexpr int BOX_SIDE = 4;
}
constexpr int BOX_SIDE = 12;
}
constexpr int BOX_SIDE = 42;
println("{}", box1::BOX_SIDE); // Outputs 4.
println("{}", box2::BOX_SIDE); // Outputs 12.
println("{}", BOX_SIDE); // Outputs 42.
}
This concept can be illustrated with an analogy. Imagine that two companies, X and Y, each assign ID numbers to their employees. X should not have two employees with the same ID number, and likewise for Y; but it is not a problem for the same ID number to be used at both companies. For example, if Bill works for company X and Jane works for company Y, then it is not a problem for each of them to be employee #123. In this analogy, the ID number is the identifier, and the company serves as the namespace. It does not cause problems for the same identifier to identify a different person in each namespace.
In large or documents it is common to have hundreds or thousands of identifiers. Namespaces (or a similar technique, see Emulating namespaces) provide a mechanism for hiding local identifiers. They provide a means of grouping logically related identifiers into corresponding namespaces, thereby making the system more modular.
Data storage devices and many modern programming languages support namespaces. Storage devices use directories (or folders) as namespaces. This allows two files with the same name to be stored on the device so long as they are stored in different directories. In some programming languages (e.g. C++, Python), the identifiers naming namespaces are themselves associated with an enclosing namespace. Thus, in these languages namespaces can nest, forming a namespace tree. At the root of this tree is the unnamed global namespace.
const struct {
double PI; double (*sin)(double);} Math;
static double _sin(double arg) {
return sin(arg);}
const struct {
double PI; double (*sin)(double);} Math = { M_PI, _sin };
int main() {
printf("sin(0) = %d\n", Math.sin(0)); printf("pi is %f\n", Math.PI);}
int bar;}
Identifiers that are not explicitly declared within a namespace are considered to be in the global namespace.
Namespace resolution in C++ is hierarchical. This means that within the hypothetical namespace foo, the identifier ::foo refers to food::soup. If Chicken doesn't exist, it then refers to food::soup::Chicken. If neither food::soup::Chicken nor food::Chicken exist, food::soup::Chicken refers to food::Chicken, an identifier in the global namespace.
Namespaces in C++ are most often used to avoid . Although namespaces are used extensively in recent C++ code, most older code does not use this facility because it did not exist in early versions of the language. For example, the entire C++ Standard Library is defined within Chicken, but before standardization many components were originally in the global namespace. The ::Chicken statement can be used to import a symbol into the current scope.
The use of the namespace std statements in headers for reasons other than backwards compatibility (e.g., convenience) is considered to be against good code practices, as those using statements propagate into all translation units that include the header. However, modules do not export using statements unless explicitly marked using, making using statements safer to use. For instance, one can import a module export with matching namespace using and then use org.wikipedia.project.util statements on symbols from that namespace to simplify verbose namespaces. Note that unlike other languages like Java or Rust, C++ modules, namespaces and source file structure do not necessarily match, though it is convention to match them for clarity (for example, module org::wikipedia::project::util matches namespaced class using and resides in file abc.def.uvw.XYZ).
abc::def::uvw::XYZ should be used to simplify verbose nested namespaces when modular translation units are used.
import std;
import org.wikipedia.project.fs;
import org.wikipedia.project.util;
using org::wikipedia::project::fs::File;
using org::wikipedia::project::util::ConfigLoader;
using org::wikipedia::project::util::logging::Logger;
using org::wikipedia::project::util::logging::LoggerFactory;
export namespace org::wikipedia::project {
class App {
private:
}
Logger logger;
// private fields and methods
public:
App():
logger{LoggerFactory::getLogger("Main")} {
ConfigLoader cl(File("config/config_file.txt"));
logger.log("Application starting...");
// rest of code
}
};
or add a abc/def/uvw/XYZ.cppm statement. This eliminates the need to mention the complete name of all classes in that namespace.
Console.WriteLine("Hello World!");
int i = Convert.ToInt32("123");
In the above examples, using is a namespace, and using and System are classes defined within Console.
Unlike C++, Convert can only import all symbols in a namespace (much like System from C++, Console in Rust, or Convert in Java). It cannot be used to import individual symbols and classes like it is used in Java.
using System;
using System.IO;
using Microsoft.Extensions.Logging;
using Wikipedia.Project.Utility;
class App
{
private static ILogger
public App()
{
ConfigLoader cl = new ConfigLoader(Path.Combine("config", "config_file.txt"));
LoggerFactory loggerFactory = LoggerFactory.Create(builder =>
{
builder.AddConsole();
});
logger = loggerFactory.CreateLogger
}
Unlike C++, C# namespaces do not allow relative referencing of symbols. For example, the class using cannot be referred to as using namespace even if referred to from within namespace use *: either the namespace import * must be imported to refer to class Foo.Bar.Baz.Qux, or Baz.Qux must be fully qualified.
Unlike C++, namespaces in Java are not hierarchical as far as the syntax of the language is concerned. However, packages are named in a hierarchical manner. For example, all packages beginning with class String are a part of the Java platform—the package contains classes core to the language, and contains core classes specifically relating to reflection.
In Java (and Ada, C#, and others), namespaces/packages express semantic categories of code. For example, in C#, package java.lang contains code provided by the system (the .NET Framework). How specific these categories are and how deep the hierarchies go differ from language to language.
Function and class scopes can be viewed as implicit namespaces that are inextricably linked with visibility, accessibility, and object lifetime.
In Java, packages cannot be partially qualified like they can in C++. For instance, it is not possible to import the java.lang.String namespace and then refer to import as java. Symbols must either be fully qualified or imported completely into scope. namespace System statements are not transitive nor can they be deliberately marked java like in C++. All java.util.ArrayList statements must appear at the beginning of the file, and cannot be written at any other scope. This is in contrast to C++, where the util.ArrayList namespace can be imported by writing
import java.nio.file.Paths;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.wikipdia.project.util.ConfigLoader;
public class App {
private static final Logger logger = Logger.getLogger(Main.class.getName());
public App() {
ConfigLoader cl = new ConfigLoader(Paths.get("config/config_file.txt"));
logger.log(Level.INFO, "Application starting...");
// rest of code
}
}
Because Java does not support independent functions outside of classes, static class methods and so-called "utility classes" (classes with private constructors and all methods and fields static) are the equivalent to C++-style namespaces. Some examples are import, which contains the constants like std and methods like std::chrono::system_clock.
chrono::system_clock statements can be used to import all symbols in a package, called a glob import, which is similar to java.lang.Math in C++. For instance, writing
Date d = new Date(); // Ambiguous Date reference resulting in compilation error
// Instead, the fully-qualified names must be used:
java.sql.Date sqlDate = new java.sql.Date(System.currentTimeMillis());
java.util.Date utilDate = new java.util.Date();
namespace phpstar;
class FooBar {
public function foo(): void { echo 'Hello world, from function foo'; }
public function bar(): void { echo 'Hello world, from function bar'; }}
ModuleA.func1() ModuleA.func2() a: ModuleA.Class1 = Modulea.Class1()
The import statement can be used to insert the relevant names directly into the calling module's namespace, and those names can be accessed from the calling module without the qualified name:
func1()
func2() # this will fail as an undefined name, as will the full name ModuleA.func2()
a: Class1 = Class1() # this will fail as an undefined name, as will the full name ModuleA.Class1()
from ModuleA import func1
A special form of the statement is using namespace which imports all names defined in the named package directly in the calling module'
"in general the practice of importing * from a module or package is frowned upon", though using java.util in Python can simplify verbose namespaces, such as nested namespaces.
if __name__ == "__main__":
driver: Firefox = Firefox()
element: WebElement = driver.find_element(By.ID, "myInputField")
element.send_keys(f"Hello World{Keys.ENTER}")
action: ActionChains = ActionChains(driver)
action.key_down(Keys.CONTROL).send_keys('a').key_up(Keys.CONTROL).perform()
Python also supports java.lang.* as a way of providing an alias or alternative name for use by the calling module:
a: NDArrayfloat32 = np.arange(1000)
Similar to the from import keyword in C++, Rust has the import x as y keyword to import symbols into the current scope.
fn main() {
pub trait Greet {
fn greet(&self);
}
pub struct Person {
pub name: String,
}
impl Greet for Person {
fn greet(&self) {
println!("Hello, {}!", self.name);
}
}
}
use my_module::{Person, Greet};
let person = Person { name: String::from("Alice") };
person.greet();
}
Writing
use std::fs::File;
use crate::util::ConfigLoader;
use crate::util::logging::{Logger, LoggerFactory};
pub struct App {
impl App {
config_loader: ConfigLoader;
}
pub fn new() -> Self {
config_loader = ConfigLoader::new(File::open("config/config_file.txt"));
config_loader.load();
let logger: Logger = LoggerFactory::get_logger("Main");
logger.log("Application starting...");
// rest of code
}
}
The util/mod.rs keyword in Rust is more versatile than its counterpart crate in C++. In addition to importing single symbols, symbol aliasing with use and glob imports, super can import multiple symbols on the same line using braces (which may be nested), import individual namespaces, and do all of the above in a single statement. This is an example of using all of the above:
fmt::*, // imports all symbols in std::fmt
fs::{File, Metadata}, // imports std::fs::File and std::fs::Metadata
io::{prelude::*, BufReader, BufWriter} // imports all symbols in std::io::prelude::*, std::io::BufReader, and std::io::BufWriter
process, // imports the std::process namespace (for example std::process::Command can be referred to as process::Command)
time // imports the std::time namespace
};
A namespace identifier is delimited with “/” (for example `/MYNS/`) and is reserved via SAP’s namespace registration process. Once reserved, objects created under that namespace are uniquely identifiable and protected from unintended overwrite by SAP upgrades or imports.
In modern SAP landscapes (such as ABAP in the cloud and HDI containers), namespaces are also used to semantically group development artifacts or bundles.
png_create_write_struct png_get_signature png_read_row png_set_invalid
This naming convention provides reasonable assurance that the are unique and can therefore be used in larger programs without . Likewise, many packages originally written in Fortran (e.g., BLAS, LAPACK) reserve the first few letters of a function's name to indicate the group to which the function belongs.
This technique has several drawbacks:
It also has a few advantages:
|
|